<template>
  <div class="main-box">
    <TreeFilter
      label="label"
      id="value"
      title="机构列表 (单选)"
      :request-api="getOrgCascaderOptionApi"
      :default-value="initParam.orgId"
      @change="changeTreeFilter"
    />
    <div class="table-box">
      <ProTable
        ref="proTableRef"
        :columns="columns"
        :request-api="getUserPageApi"
        :init-param="initParam"
        :search-col="{ xs: 1, sm: 1, md: 2, lg: 3, xl: 3 }"
      >
        <!-- 表格 header 按钮 -->
        <template #tableHeader>
          <el-button v-auth="'sys:user:add'" type="primary" :icon="CirclePlus" @click="handleAdd">新增用户</el-button>
          <el-button v-auth="'sys:user:import'" type="primary" :icon="Upload" plain @click="batchAdd">批量添加用户</el-button>
          <el-button v-auth="'sys:user:export'" type="primary" :icon="Download" plain @click="downloadFile">
            导出用户数据
          </el-button>
        </template>
        <!-- 锁定 -->
        <template #errorNum="{ row }">
          {{ row.errorNum < 3 ? "--" : "锁定" }}
        </template>
        <!-- 状态 -->
        <template #isEnable="scope">
          <el-switch
            v-model="scope.row.isEnable"
            :loading="scope.row.loading"
            active-text="已启用"
            inactive-text="已禁用"
            inline-prompt
            :before-change="handleEnable.bind(scope, scope.row)"
          />
        </template>
        <!-- 表格操作 -->
        <template #operation="{ row }">
          <div class="operation-box">
            <el-button v-auth="'sys:user:edit'" type="primary" link :icon="EditPen" @click="handleEdit(row)">编辑</el-button>
            <el-button v-auth="'sys:user:del'" type="danger" link :icon="Delete" @click="handleDelete(row)">删除</el-button>
            <el-dropdown :hide-on-click="false" class="more-btn">
              <span class="more-btn-span"> <More /> 更多 </span>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item>
                    <el-button v-auth="'sys:user:unlock'" type="primary" link :icon="Lock" @click="handleUnlock(row)">
                      解锁
                    </el-button>
                  </el-dropdown-item>
                  <el-dropdown-item>
                    <el-button v-auth="'sys:user:reset'" type="primary" link :icon="Refresh" @click="handleReset(row)">
                      重置密码
                    </el-button>
                  </el-dropdown-item>
                  <el-dropdown-item>
                    <el-button v-auth="'sys:user:loginLog'" type="primary" link :icon="LogIcon" @click="openUserLoginLog(row)">
                      登录记录
                    </el-button>
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </template>
      </ProTable>
      <user-edit ref="editDialogRef" />
      <user-import ref="importDialogRef" />
      <user-login-log ref="userLoginLogRef" />
    </div>
  </div>
</template>
<script setup lang="ts">
import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
import type { SysUser } from "@/api/interface";
import { ref, reactive } from "vue";
import { ElMessageBox, ElNotification } from "element-plus";
import { useHandleData } from "@/hooks/useHandleData";
import { useDownload } from "@/hooks/useDownload";
import { statusConst, userSexConst } from "@/utils/dict";
import { getOrgCascaderOptionApi } from "@/api/modules/system/org";
import {
  addUserApi,
  editUserApi,
  getUserPageApi,
  deleteUserApi,
  switchEnableUserApi,
  unlockUserApi,
  resetUserPassWordApi,
  exportUserApi,
  batchAddUserApi
} from "@/api/modules/system/user";
import { downloadTemplateApi } from "@/api/modules/system/template";
import ProTable from "@/components/ProTable/index.vue";
import TreeFilter from "@/components/TreeFilter/index.vue";
import UserEdit from "./components/edit.vue";
import UserImport from "./components/import.vue";
import UserLoginLog from "./components/userLoginLog.vue";

import CirclePlus from "~icons/ep/circle-plus";
import Delete from "~icons/ep/delete";
import EditPen from "~icons/ep/edit-pen";
import Download from "~icons/ep/download";
import Upload from "~icons/ep/upload";
import More from "~icons/ep/more";
import Lock from "~icons/ep/lock";
import Refresh from "~icons/ep/refresh";
import LogIcon from "~icons/ep/document";

defineOptions({
  name: "SystemUser"
});

/** 表格实例 */
const proTableRef = ref<ProTableInstance>();
/** 编辑用户弹窗实例 */
const editDialogRef = ref<InstanceType<typeof UserEdit> | null>(null);
/** 导入用户弹窗实例 */
const importDialogRef = ref<InstanceType<typeof UserImport> | null>(null);
/** 用户登录日志弹窗实例 */
const userLoginLogRef = ref<InstanceType<typeof UserLoginLog> | null>(null);

/** 表单初始化参数 */
const initParam = reactive({ orgId: "" });
/** 表格配置项 */
const columns = reactive<ColumnProps<SysUser.Result>[]>([
  { type: "index", label: "#", width: 80 },
  { prop: "nickName", label: "用户昵称", width: 120, search: { el: "input" } },
  { prop: "sex", label: "性别", width: 100, sortable: true, enum: userSexConst, search: { el: "select" } },
  { prop: "phone", label: "联系电话" },
  { prop: "orgName", label: "所属机构" },
  { prop: "roleName", label: "角色" },
  { prop: "errorNum", label: "锁定", width: 100 },
  { prop: "isEnable", label: "状态", width: 100, enum: statusConst, search: { el: "select" } },
  { prop: "operation", label: "操作", width: 210, fixed: "right" }
]);

/**
 * 树形筛选切换
 *
 * @param val 选中的机构id
 * @returns void
 */
const changeTreeFilter = (val: string) => {
  initParam.orgId = val;
  proTableRef.value!.pageable.pageIndex = 1;
};

/**
 * 新增用户
 *
 * @returns void
 */
const handleAdd = () => {
  const editParams = {
    title: "新增用户",
    user: {},
    getTableList: proTableRef.value?.getTableList,
    submitApi: addUserApi
  };
  editDialogRef.value?.acceptParams(editParams);
};

/**
 * 编辑用户
 *
 * @param row 选中的用户
 * @returns void
 */
const handleEdit = (param: Partial<SysUser.Result>) => {
  const editParams = {
    title: "编辑用户",
    user: { ...param },
    getTableList: proTableRef.value?.getTableList,
    submitApi: editUserApi
  };
  editDialogRef.value?.acceptParams(editParams);
};

/**
 * 启用/禁用用户
 *
 * @param param 选中的用户
 * @returns void
 */
const handleEnable = (param: Partial<SysUser.Result> & { loading?: boolean }) => {
  param.loading = true;
  return switchEnableUserApi({ id: param.id! })
    .then(({ data }) => {
      if (data) {
        return Promise.resolve(true);
      } else return Promise.reject(new Error("修改状态失败"));
    })
    .finally(() => {
      param.loading = false;
    });
};

/**
 * 解锁用户
 *
 * @param param 选中的用户
 * @returns void
 */
const handleUnlock = (param: SysUser.Result) => {
  if (param.errorNum < 3) {
    return ElNotification({
      title: "温馨提示",
      message: "用户未锁定！",
      type: "warning"
    });
  }

  useHandleData(unlockUserApi, { id: param.id }, `解锁【${param.nickName}】用户`).then(res => {
    if (res) proTableRef.value?.getTableList();
  });
};

/**
 * 重置用户密码
 *
 * @param param 选中的用户
 * @returns void
 */
const handleReset = (param: SysUser.Result) => {
  useHandleData(resetUserPassWordApi, { id: param.id }, `重置【${param.nickName}】用户密码?`);
};

/**
 * 删除用户信息
 *
 * @param param 选中的用户
 * @returns void
 */
const handleDelete = (param: SysUser.Result) => {
  useHandleData(deleteUserApi, { ids: [param.id] }, `删除【${param.nickName}】用户`).then(res => {
    if (res) proTableRef.value?.getTableList();
  });
};

/**
 * 打开用户登录日志抽屉
 *
 * @param param 选中的用户
 * @returns void
 */
const openUserLoginLog = (param: SysUser.Result) => {
  userLoginLogRef.value?.acceptParams({
    account: param.account,
    userName: param.name
  });
};

/**
 * 导出用户数据
 *
 * @returns void
 */
const downloadFile = () => {
  ElMessageBox.confirm("确认导出用户数据?", "温馨提示", { type: "warning" }).then(() =>
    useDownload(exportUserApi, "", proTableRef.value?.searchParam)
  );
};

/**
 * 批量添加用户
 *
 * @returns void
 */
const batchAdd = () => {
  const importParams = {
    title: "批量添加用户",
    form: {},
    tempApi: downloadTemplateApi,
    importApi: batchAddUserApi,
    getTableList: proTableRef.value?.getTableList
  };
  importDialogRef.value?.acceptParams(importParams);
};
</script>

<style lang="scss" scoped>
.operation-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  .more-btn {
    margin-left: 12px;
    .more-btn-span {
      display: inline-flex;
      gap: 6px;
      align-items: center;
      color: var(--el-color-primary);
      cursor: pointer;
    }
  }
}
</style>
